#include <iostream>
#include <exception>
#include <map>
#include <vector>
#include <set>
#include <cmath>
#include <sstream>

//#define NDEBUG
#include <assert.h>


namespace mkuz
{

namespace math
{
/**
 * Greatest Common Divisior, Euclidean algorithm
 */
int gcd(int a, int b)
{
    if (b == 0)
        return a;
    else
        return gcd(b, a % b);
}

template<typename T>
T abs(T a)
{
    return a < T(0) ? -a : a;
}

int lcm(int a, int b)
{
    return abs(a * b) / gcd(a, b);
}

class rational
{
public:

    rational(const int n_ = 0, const int d_ = 1)
    {
        assert(d_ != 0);
        n = d_ < 0 ? -n_ : n_;
        d = d_ < 0? -d_ : d_;
        if (d_ > 50)
            simplify();

        //TODO
        //assert( (float)(*this) == 1 || (float)(*this) == 0 || (float)(*this) == -1);
    }

    bool operator == (int n_)
    {
        if (is_int())
            return n / d == n_;
        return false;
    }

    bool operator == (const rational & val) const
    {
        return n * val.d == val.n * d;
    }

    bool operator != (int n_)
    {
        return !((*this) == n_);
    }

    bool operator != (const rational & val) const
    {
        return !((*this) == val);
    }

    bool operator > (const rational & val) const
    {
        return n * val.d > val.n * d;
    }

    bool operator < (const rational & val) const
    {
        return n * val.d < val.n * d;
    }

    bool operator >= (const rational & val) const
    {
        return n * val.d >= val.n * d;
    }

    bool operator <= (const rational & val) const
    {
        return n * val.d <= val.n * d;
    }

    bool is_int() const
    {
        return n % d == 0;
    }

    operator const float () const
    {
        return (float) n / d;
    }

    rational operator + (const rational & val) const
    {
        int n_ = n * val.d + val.n * d;
        int d_ = d * val.d;
        return rational(n_, d_);
    }

    rational operator - () const
    {
        return rational(-n, d);
    }

    rational operator - (const rational & val) const
    {
        int n_ = n * val.d - val.n * d;
        int d_ = d * val.d;
        return rational(n_, d_);
    }

    rational operator * (const rational & val) const
    {
        int n_ = n * val.n;
        int d_ = d * val.d;
        return rational(n_, d_);
    }

    rational operator / (const rational & val) const
    {
        int n_ = n * val.d;
        int d_ = d * val.n;
        return rational(n_, d_);
    }

    /*TODO
    rational & operator += (const rational & val)
    rational & operator *= (const rational & val)
    rational & operator -= (const rational & val)
    rational & operator /= (const rational & val)
    */

    void simplify()
    {
        int gcd = math::gcd(n, d);
        n = n / gcd;
        d = d / gcd;
        if (d < 0)
        {
            n = -n;
            d = -d;
        }
    }

    std::string to_s() const
    {
        std::ostringstream ss;
        ss << n << "/" << d;
        return ss.str();
    }

    float to_f() const
    {
        return (float)n / d;
    }


private:
    int n;
    int d;
};
typedef rational r;

}

///////////////////////////////////////////////////

template <typename T>
class linsys
{
public:

    class row
    {
    public:
        typedef std::pair<int, T> elem;
        typedef std::map<int, T> elems;
        typedef typename elems::const_iterator const_iterator;

        row(const int real_length)
        {
            real_len = real_length;
            main_ind = -1;
        }

        row & operator << (const elem & el)
        {
            assert(el.first < real_len);
            //assert(el.second != T(0));
            if (el.second == T(0))
                return *this;

            assert(data.find(el.first) == data.end());
            data.insert(el);

            if (main_ind == -1 || el.first < main_ind)
            {
                main_ind = el.first;
            }
            return *this;
        }

        row & operator << (const int & index)
        {
            (*this) << elem(index, 1);
            return *this;
        }

        row operator + (const row & val) const
        {
            row retval(real_len);

            for(const_iterator it = data.begin(); it != data.end(); ++it)
            {
                assert(it->second != T(0));
                T v = it->second + val[it->first];
                if (v != 0)
                    retval << elem(it->first, v);
            }
            for(const_iterator it = val.begin(); it != val.end(); ++it)
            {
                if (data.find(it->first) == data.end())
                {
                    assert(it->second != T(0));
                    retval << elem(it->first, it->second);
                }
            }

            return retval;
        }

        row operator - () const
        {
            row retval(real_len);

            for(const_iterator it = data.begin(); it != data.end(); ++it)
            {
                assert(it->second != T(0));
                retval << elem(it->first, -it->second);
            }
            return retval;
        }

        row operator - (const row & val) const
        {
            return (*this) + (-val);
        }

        row operator * (const T val) const
        {
            row retval(real_len);
            for(const_iterator it = data.begin(); it != data.end(); ++it)
            {
                assert(it->second != T(0));
                T v = it->second * val;
                if (v != 0)
                    retval << elem(it->first, v);
                //assert(math::abs(v) < T(50000));
            }
            return retval;
        }

        row operator / (const T val) const
        {
            return (*this) * (T(1) / val);
        }

        bool is_zero() const
        {
            return main_ind == -1;
        }
        bool is_one() const
        {
            return data.size() == 1 && mv() == T(1);
        }

        const int & mi() const
        {
            return main_ind;
        }

        const T mv() const
        {
            assert(main_ind >= 0);
            return (*this)[main_ind];
        }

        T operator [] (const int j) const
        {
            T retval = 0;
            const_iterator it = data.find(j);
            if (it != data.end())
            {
                retval = it->second;
            }
            return retval;
        }

        std::string to_s() const
        {
            std::ostringstream ss;
            ss << "[";
            for(int i = 0; i < real_len; i++)
                ss << ((*this)[i]) << (i == real_len -1 ? "" : ", ");
            ss << "]";
            return ss.str();
        }

        const_iterator begin() const
        {
            return data.begin();
        }
        const_iterator end() const
        {
            return data.end();
        }
        const_iterator lower_bound(const int x) const
        {
            return data.lower_bound(x);
        }

    private:
        elems data;
        int main_ind;
        int real_len;
    };

    typedef std::vector<T> vec;

    std::string static vec_to_s(const vec & val)
    {
        std::ostringstream ss;
        ss << "[";
        for (int i = 0, n = val.size(); i < n; i++)
        {
            ss << val[i] << (i != n - 1 ? ", " : "");
        }
        ss << "]";
        return ss.str();
    }

    class matrix
    {
    public:
        typedef std::vector<row> rows;

        matrix(const int max_rank)
        {
            data.resize(max_rank, row(max_rank));
            rnk = 0;
        }

        int max_rank() const
        {
            return data.size();
        }

        int rank() const
        {
            return rnk;
        }

        row & operator [] (const int i)
        {
            return data[i];
        }
        const row & operator [](const int i) const
        {
            return data[i];
        }

        bool add(const row & ai, const T & bi, vec & b)
        {
            bool added = false;

            assert(0 <= rnk && rnk < max_rank());
            if (rank() >= max_rank())
                return false;

            row at1 = ai;
            T bt1 = bi;
            while (true)
            {
                if (!at1.is_zero())
                {
                    const row & at2 = data[at1.mi()];
                    if (!at2.is_zero())
                    {
                        assert(at2.mv() != T(0));
                        T k = at1.mv() / at2.mv();
                        at1 = at1 - (at2 * k);
                        bt1 = bt1 - (b[at2.mi()] * k);
                        continue;
                    } else
                    {
                        assert(data[at1.mi()].is_zero());
                        data[at1.mi()] = at1;
                        b[at1.mi()] = bt1;
                        rnk++;
                        added = true;
                    }
                }
                break;
            }

            return added;
        }

        /*void to_identical(vec & b)
        {
            assert(triangular());

            for (int i = 0; i < max_rank(); i++)
            {
                row & r1 = data[i];
                //TODO assert(!r1.is_zero());
                if (r1.is_zero()) continue;

                int index = i + 1;
                typename row::const_iterator it;
                while ((it = r1.lower_bound(index)) != r1.end())
                {
                    int j = it->first;

                    const row & r2 = data[j];
                    //TODO assert(r2.mi() > i && r2.mi() == j);
                    //TODO assert(!r2.is_zero());
                    if (r2.is_zero()) break;

                    T k = r1[j] / r2[j];
                    r1 = r1 - (r2 * k);

                    b[i] = b[i] - (b[j] * k);

                    index = j + 1;
                }
                T d = r1.mv();
                r1 = r1 / d;
                b[i] = b[i] / d;
            }
            std::cout << "a = " << to_s() << std::endl;
            std::cout << "b = " << vec_to_s(b) << std::endl;

            assert(identical());
        }*/

        static void reduce_func_def (matrix & m, vec & b)
        {
            //do nothing
        }

        template<typename reduce_func>
        void to_identical(vec & b, reduce_func reduce)
        {
            assert(triangular());

            while (true)
            {
                for (int i = 0; i < max_rank(); i++)
                {
                    row & r1 = data[i];
                    if (r1.is_zero())
                        continue;
                    assert(!r1.is_zero());

                    int index = i + 1;
                    typename row::const_iterator it;
                    while ((it = r1.lower_bound(index)) != r1.end())
                    {
                        int j = it->first;

                        const row & r2 = data[j];
                        if (r2.is_zero())
                        {
                            break;
                        }

                        assert(r2.mi() > i && r2.mi() == j);
                        assert(!r2.is_zero());

                        T k = r1[j] / r2[j];
                        r1 = r1 - (r2 * k);

                        b[i] = b[i] - (b[j] * k);

                        index = j + 1;
                    }
                    T d = r1.mv();
                    r1 = r1 / d;
                    b[i] = b[i] / d;
                }

                std::cout << "r1 = " << rank() << std::endl;
                int prev_rnk = rank();
                if (rank() < max_rank())
                {
                    reduce(*this, b);
                }
                std::cout << "r2 = " << rank() << std::endl;
                if (prev_rnk != rank())
                    continue;
                //if (rank() < max_rank()) //TODO
                //    continue;
                break;
            }

            //std::cout << "a = " << to_s() << std::endl;
            //std::cout << "b = " << vec_to_s(b) << std::endl;

            assert(identical());
        }

        void to_identical(vec & b)
        {
            to_identical(b, reduce_func_def);
        }


        bool triangular() const
        {
            for(int i = 0, n = data.size(); i < n; i++)
            {
                const row & r_ = data[i];
                if (r_.mi() < i && r_.mi() != -1)
                    return false;
            }
            return true;
        }

        bool identical() const
        {
            for (int i = 0; i < max_rank(); i++)
            {
                const row & r_ = data[i];
                for (typename row::const_iterator it = r_.begin(); it != r_.end(); ++it)
                {
                    assert(it->second != T(0));
                    if (it->first != i || it->second != T(1))
                    {
                        return false;
                    }
                }
            }
            return true;
        }

        std::string to_s() const
        {
            std::ostringstream ss;
            ss << "[";
            for (int i = 0, n = data.size(); i < n; i++)
            {
                ss << data[i].to_s();
                ss << (i == n - 1 ? "" : ", \n");
            }
            ss << "]";
            return ss.str();
        }

    private:
        rows data;
        int rnk;
    };

public:

    linsys(const int max_rank) : a(max_rank)
    {
        b.resize(max_rank, T(0));
    }

    bool add(const row & ai, const T & bi)
    {
        return a.add(ai, bi, b);
    }

    int equats() const
    {
        return a.rank();
    }
    int vars() const
    {
        return a.max_rank();
    }

    template <typename reduce_func>
    bool solve(vec & x, reduce_func reduce)
    {
        //TODO if (a.rank() == a.max_rank())
        {
            a.to_identical(b, reduce); //TODO
            x = b;
            return true;
        }
        return false;
    }

private:
    matrix a;
    vec b;
};

class sudoku
{
public:
    typedef std::vector<std::vector<int> > area_t;

    sudoku(const area_t & area_, const int block_)
        : BLOCK(block_), SIDE(BLOCK * BLOCK)
    {
        area = area_;
        if (!verify())
            assert(false);
    }

    template <int block>
    static area_t to_area(const int arr[block * block][block * block])
    {
        const int side = block * block;
        area_t a;
        a.resize(side);
        for(int i = 0; i < side; i++)
        {
            a[i].resize(side);
            for(int j = 0; j < side; j++)
                a[i][j] = arr[i][j];
        }
        return a;
    }

    bool verify() const
    {
        //square
        for (int i = 0, rows = area.size(); i < rows; i++)
        {
            if (rows != SIDE || (int)area[i].size() != SIDE)
                return false;
        }

        //numbers are from 0 to n (zero means a cell is undefined)
        for (int i = 0; i < SIDE; i++)
        {
            for (int j = 0; j < SIDE; j++)
            {
                if (!(0 <= area[i][j] && area[i][j] <= SIDE))
                    return false;
            }
        }

        //unique numbers in a row
        for (int i = 0; i < SIDE; i++)
        {
            std::vector<int> nums;
            nums.resize(SIDE + 1);
            for (int j = 0; j < SIDE; j++)
            {
                ++nums[area[i][j]];
                if (area[i][j] != 0 && nums[area[i][j]] > 1)
                    return false;
            }
        }

        //unique numbers in a column
        for (int j = 0; j < SIDE; j++)
        {
            std::vector<int> nums;
            nums.resize(SIDE + 1);
            for (int i = 0; i < SIDE; i++)
            {
                ++nums[area[i][j]];
                if (area[i][j] != 0 && nums[area[i][j]] > 1)
                    return false;
            }
        }

        //unique numbers in a block
        for (int b = 0; b < SIDE; b++)
        {
            std::vector<int> nums;
            nums.resize(SIDE + 1);

            int bi = (b / BLOCK) * BLOCK;
            int bj = (b % BLOCK) * BLOCK;
            for (int i = bi; i < bi + BLOCK; i++)
            {
                for (int j = bj; j < bj + BLOCK; j++)
                {
                    ++nums[area[i][j]];
                    if (area[i][j] != 0 && nums[area[i][j]] > 1)
                        return false;
                }
            }
        }

        return true;
    }

    typedef mkuz::linsys<math::r> ls; // TODO linsys<int>

    struct reduce_func
    {
        reduce_func(ls * s_, const int block) :
            s(s_), BLOCK(block), SIDE(BLOCK * BLOCK)
        {
        }

        void operator ()(ls::matrix & m, ls::vec & b)
        {
            assert(m.rank() < m.max_rank());
            assert(m.max_rank() == (int)b.size());
            assert(m.triangular());

            for (int i = 0; i < m.max_rank(); i++)
            {
                for (ls::row::const_iterator it = m[i].begin(); it
                        != m[i].end(); ++it)
                {
                    int j = it->first;
                    if (m[j].is_one() && b[j] == 1)
                    {
                        int c = (j / (SIDE * SIDE)) * (SIDE * SIDE);
                        int index = j;
                        int ii = (index - c) / SIDE;
                        int jj = (index - c) % SIDE;

                        std::set<int> inds;
                        inds.insert(index);

                        for (int k = 0; k < SIDE - 1; k++)
                        {
                            inds.insert(c + ii * SIDE + k); // row
                            inds.insert(c + k * SIDE + jj); // column
                            inds.insert(k * SIDE * SIDE + ii * SIDE + jj); // other numbers
                        }

                        // block
                        int bi0 = (ii / BLOCK) * BLOCK;
                        int bj0 = (jj / BLOCK) * BLOCK;
                        for (int bi = bi0; bi < bi0 + BLOCK; bi++)
                            for (int bj = bj0; bj < bj0 + BLOCK; bj++)
                                inds.insert(c + bi * SIDE + bj);

                        for (std::set<int>::const_iterator it = inds.begin(); it
                                != inds.end() && s->equats() < s->vars(); ++it)
                        {
                            if ((*it) != index)
                                s->add(ls::row(s->vars()) << (*it), 0);
                        }

                    }

                }
            }
            assert(m.triangular());

        }

    private:
        ls * s;
        const int BLOCK;
        const int SIDE;
    };

    bool solve()
    {

        const int VARS = SIDE * SIDE * SIDE;

        ls s(VARS);
        // X = A^-1 * B

        // init a and b

        // a number is unique in a row
        for (int c = 0; c < VARS; c += SIDE)
        {
            ls::row row(s.vars());
            for (int k = 0; k < SIDE; k++)
                row << c + k;
            s.add(row, 1);
        }
        assert(s.equats() == SIDE * SIDE);

        // a number is unique in a column
        for (int c = 0; c < VARS; c += SIDE * SIDE)
        {
            for (int j = c; j < c + (SIDE - 1); j++)
            {
                ls::row row(s.vars());
                for(int k = 0; k < SIDE; k++)
                    row << j + k * SIDE;
                s.add(row, 1);
            }
        }
        assert(s.equats() == SIDE * SIDE + SIDE * (SIDE - 1));

        // a number is unique in a block
        for (int c = 0; c < VARS; c += SIDE * SIDE)
        {
            for(int bi = 0; bi < BLOCK - 1; bi++)
            {
                for(int bj = 0; bj < BLOCK - 1; bj++)
                {
                    ls::row row(s.vars());
                    for (int i = 0; i < BLOCK; i++)
                    {
                        for (int j = 0; j < BLOCK; j++)
                        {
                            int index = (c + bi * SIDE * BLOCK + bj * BLOCK) + i * SIDE + j;
                            row << index;
                        }
                    }
                    s.add(row, 1);
                }
            }
        }

        assert(s.equats() == SIDE * SIDE + SIDE * (SIDE - 1) + SIDE * (BLOCK - 1) * (BLOCK - 1));

        // a cell contains one number
        for (int i = 0; i < SIDE - 1; i++)
        {
            for (int j = 0; j < SIDE - 1; j++)
            {
                ls::row row(s.vars());
                for(int c = 0; c < VARS; c += SIDE * SIDE)
                    row << c + i * SIDE + j;
                s.add(row, 1);
            }
        }

        assert(BLOCK != 2 || (BLOCK == 2 && s.equats() == 40));

        // givens
        /*for(int i = 0; i < SIDE; i++)
        {
            for (int j = 0; j < SIDE; j++)
            {
                int v = area[i][j];
                assert(0 <= v && v <= SIDE);
                if (v != 0)
                {
                    int c = (v - 1) * SIDE * SIDE;
                    int index = c + i * SIDE + j;

                    std::set<int> inds;
                    inds.insert(index);

                    for (int k = 0; k < SIDE - 1; k++)
                    {
                        inds.insert(c + i * SIDE + k); // row
                        inds.insert(c + k * SIDE + j); // column
                        inds.insert(k * SIDE * SIDE + i * SIDE + j); // other numbers
                    }

                    // block
                    int bi0 = (i / BLOCK) * BLOCK;
                    int bj0 = (j / BLOCK) * BLOCK;
                    for (int bi = bi0; bi < bi0 + BLOCK; bi++)
                        for (int bj = bj0; bj < bj0 + BLOCK; bj++)
                            inds.insert(c + bi * SIDE + bj);

                    for(std::set<int>::const_iterator it = inds.begin();
                            it != inds.end() && s.equats() < s.vars(); ++it)
                    {
                        int b = (*it) == index ? 1 : 0;
                        s.add(ls::row(s.vars()) << (*it), b);
                    }
                }
            }
        }*/
        for (int i = 0; i < SIDE; i++)
        {
            for (int j = 0; j < SIDE; j++)
            {
                int v = area[i][j];
                assert(0 <= v && v <= SIDE);
                if (v != 0)
                {
                    int c = (v - 1) * SIDE * SIDE;
                    int index = c + i * SIDE + j;
                    s.add(ls::row(s.vars()) << index, 1);
                }
            }
        }

        std::cout << "Found equations: " << s.equats() << " out of " << s.vars() << std::endl;

        reduce_func reduce(&s, BLOCK);

        // find X
        ls::vec x;
        bool solved = s.solve(x, reduce);
        if (solved)
        {
            assert((int)x.size() == VARS);
            for (int k = 0; k < VARS; k++)
            {
                if (x[k] != 0)
                {
                    assert(x[k] == 1);
                    int digit = k / (SIDE * SIDE) + 1;
                    int l = k % (SIDE * SIDE);
                    int i = l / SIDE;
                    int j = l % SIDE;
                    area[i][j] = digit;
                }
            }
        }
        assert(verify());
        return solved;
    }

    std::string to_s() const
    {
        std::ostringstream ss;
        ss << "[";
        for (int i = 0, rows = area.size(); i < rows; i++)
        {
            ss << "[";
            for (int j = 0, cols = area[i].size(); j < cols; j++)
                ss << area[i][j] << (j != cols - 1 ? ", " : "");
            ss << (i != rows - 1 ? "],\n" : "]");
        }
        ss << "]";
        return ss.str();
    }



private:
    area_t area;
    const int BLOCK;
    const int SIDE;
};

}

int main() {
    //assert(false);

    using namespace mkuz;

    const int a1[4][4] = {
         {1,0, 0,0},
         {0,0, 2,1},
         {0,0, 0,2},
         {0,4, 0,0}
    };
    sudoku sud1(sudoku::to_area<2>(a1), 2);
    std::cout << "Problem: " << std::endl << sud1.to_s() << std::endl;
    if (sud1.solve())
    {
        std::cout << "Solution: " << std::endl << sud1.to_s() << std::endl;
    } else
    {
        std::cout << "No solution has been found" << std::endl;
    }

    ///
    /*int a2[9][9] = { //easy
            {0,0,3, 1,5,9, 6,2,0},
            {0,0,0, 7,0,3, 8,0,0},
            {0,2,0, 0,6,0, 0,0,3},

            {2,0,6, 0,0,5, 3,0,9},
            {0,3,5, 0,1,2, 0,8,6},
            {8,1,0, 0,7,0, 2,4,5},

            {0,0,0, 6,9,7, 0,0,0},
            {0,4,0, 2,3,0, 0,0,0},
            {3,0,0, 5,0,0, 0,0,0}
        };*/
    /*int a2[9][9] = { //very easy
            {1,0,0, 9,8,2, 0,4,6},
            {9,6,0, 0,0,0, 0,0,2},
            {0,0,8, 7,5,0, 1,9,0},

            {6,0,4, 8,0,7, 9,0,0},
            {0,0,9, 1,0,0, 0,0,0},
            {0,0,0, 6,0,4, 8,1,7},

            {8,0,0, 0,0,9, 0,0,0},
            {5,0,1, 2,4,0, 0,0,9},
            {0,9,6, 0,7,0, 0,0,8}
    };*/
    /*int a2[9][9] = {
                {0,8,0, 4,0,2, 0,0,0},
                {6,0,3, 0,5,0, 0,0,0},
                {0,2,0, 0,0,0, 0,8,0},

                {0,0,0, 0,8,0, 0,0,4},
                {0,0,0, 2,0,1, 5,9,6},
                {5,0,0, 7,4,0, 3,0,0},

                {1,0,0, 0,2,0, 0,0,0},
                {0,5,0, 1,7,0, 2,6,3},
                {0,0,4, 0,9,8, 0,0,7}
        };*/
    /*int a2[9][9] = { //very very easy
            {8,1,0, 0,0,0, 0,6,5},
            {2,0,7, 0,0,0, 1,0,4},
            {3,4,0, 6,8,1, 9,0,2},

            {1,8,4, 7,0,9, 0,0,6},
            {7,0,2, 3,4,0, 0,1,0},
            {0,0,0, 0,1,5, 2,0,7},

            {9,2,6, 1,0,0, 0,0,8},
            {5,0,0, 9,0,7, 4,0,1},
            {4,0,0, 2,0,0, 6,0,3}
    };*/
    /*
    int a2[9][9] = {
            {1,7,3, 2,5,8, 9,4,6},
            {9,2,4, 7,6,1, 5,8,3},
            {8,5,6, 4,3,9, 2,7,1},

            {7,4,8, 1,9,3, 6,5,2},
            {2,6,9, 5,4,7, 1,3,8},
            {5,3,1, 8,2,6, 7,9,4},

            {6,9,5, 3,8,2, 4,1,7},
            {3,1,2, 9,7,4, 8,6,5},
            {4,8,7, 6,1,5, 3,2,9}
    };

     */
    int a2[9][9] = {
            {1,7,3, 2,5,8, 9,4,0},
            {0,0,4, 7,0,1, 0,0,0},
            {0,0,6, 4,0,9, 2,0,1},

            {7,0,8, 1,0,3, 6,0,2},
            {2,0,9, 0,0,7, 0,0,8},
            {5,0,0, 8,0,6, 0,9,4},

            {0,9,5, 3,0,2, 4,1,7},
            {3,0,0, 0,0,4, 8,0,5},
            {4,0,0, 0,0,5, 3,2,9}
    };
    sudoku sud2(sudoku::to_area<3>(a2), 3);
    std::cout << "Problem: " << std::endl << sud2.to_s() << std::endl;
    if (sud2.solve())
    {
        std::cout << "Solution: " << std::endl << sud2.to_s() << std::endl;
    } else
    {
        std::cout << "No solution has been found" << std::endl;
    }
    return 0;
}

